import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

public class UDPEchoServer {
    private DatagramSocket socket = null;

    //创建socket对象，代表网卡文件
    //读这个文件就等于从网卡中收数据，写这个文件就等于让网卡发数据
    public UDPEchoServer(int port) throws SocketException {
        socket = new DatagramSocket(port);//指定端口号
    }

    public void start() throws IOException {
        System.out.println("服务器启动");

        while(true){
            //循环一次相当于一次请求
            //处理请求时，典型的服务器分为三个步骤：

            //1、读取请求并解析

            //    DatagramPacket 相当于一个UDP数据报，此处传入字节数组，就保存UDP数据报的载荷部分
            //    其中包括报头+载荷（这里通过 new 字节数组来保存）
            DatagramPacket requestPacket = new DatagramPacket(new byte[4096], 4096);
            socket.receive(requestPacket);//输出型参数

            //    把UDP数据包载荷（二进制数据）取出来转为字符串：
            //     1）通过requestPacket.getData()拿到DatagramPacket中的字节数组
            //     2）通过requestPacket.getLength()拿到有效数据的长度
            //     3）根据字节数组，构造出一个String
            String request = new String(requestPacket.getData(),0,requestPacket.getLength());

            //2、根据请求计算相应（也是服务器的核心逻辑）
            String response = process(request);

            //3、把相应返回给客户端

            //    根据response构造DatagramPacket，这里是响应数据报，发送客户端
            //     1）通过response.getBytes()拿到字节数组
            //     2）response.getBytes().length拿到字节数组长度
            //          此处不能使用response.length，因为response.length拿到的是字符数组的长度，单位是字符
            //     3） requestPacket.getSocketAddress()拿到客户端的IP和端口号（数据从哪里来就回到哪里去）
            DatagramPacket responsePacket = new DatagramPacket(response.getBytes(),
                    response.getBytes().length,
                    requestPacket.getSocketAddress());

            //依据responsePacket中的IP和目的端口发送数据
            socket.send(responsePacket);


            //4、打印日志 记录客户端/服务端交互过程
            System.out.printf("[%s:%d] req: %s, resp: %s\n",
                    requestPacket.getAddress().toString(),
                    requestPacket.getPort(),
                    request, response);
        }

    }

    //此处是回显逻辑，请求==响应
    public String process(String request){
        return request;
    }

    static void main() throws IOException {
        UDPEchoServer server = new UDPEchoServer(9091);
        server.start();
    }
}
